<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=no">
    <title>移动盘点机</title>
    <script src="vue.js"></script>
    <script src="xlsx.full.min.js"></script>
  
</head>

<body>
    <div id="app">
        <div class="container">
            <header class="header">
                <h1 class="title">移动盘点机</h1>

            </header>

            <div class="control-panel">
                <div class="input-total-container">
                    <input ref="barcodeInput" class="input-box" v-model="barcode" placeholder="扫描或输入条码"
                        @keyup.enter="addBarcode">

                    <div class="total-panel">
                        总数<span class="total-number">{{ getTotalQuantity() }}</span>
                        <input type="checkbox" v-model="showAndStoreDetails">
                        商品详情
                        <input type="checkbox" v-model="allowDuplicateBarcodes">唯一码 截取
                        <input class="input-box" v-model.number="trimLength" type="number" min="1" max="16"
                            placeholder="截取位数" style="width: 50px;">位
                    </div>
                </div>
                <div class="button-group">
                    <button class="btn primary" @click="addBarcode">添加</button>
                    <button class="btn success" @click="exportToExcel">导出EXCEL</button>
                    <button class="btn danger" @click="clearLocalStorage">全部清空</button>
                </div>
            </div>

            <div class="current-info compact">
                <div class="info-row">

                    <div class="info-item">
                        <label>当前款号</label>
                        <span>{{ spdm }}</span>
                    </div>
                    <div class="info-item">
                        <label>颜色</label>
                        <span>{{ ggmc }}</span>
                    </div>
                    <div class="info-item">
                        <label>尺码</label>
                        <span>{{ ggmc2 }}</span>
                    </div>
                </div>
            </div>

            <div class="table-container">
                <table class="bordered-table">
                    <thead>
                        <tr>
                            <th>唯一码</th>
                            <th>商品码</th>
                            <th>数量</th>
                            <th>操作</th>
                            <!-- 根据开关状态决定是否显示列 -->
                            <th v-if="showAndStoreDetails">款号</th>
                            <th v-if="showAndStoreDetails">颜色</th>
                            <th v-if="showAndStoreDetails">颜色代码</th>
                            <th v-if="showAndStoreDetails">尺码</th>
                            <th v-if="showAndStoreDetails">尺码代码</th>
                        </tr>
                    </thead>
                    <tbody>
                        <tr v-for="(barcode, index) in paginatedBarcodes" :key="index">
                            <td :class="{ 'duplicate-barcode': isDuplicateBarcode(barcode) }" data-label="唯一码">{{
                                barcode }}</td>
                            <td data-label="商品条码">{{ getProductCode(barcode) }}</td>
                            <td data-label="数量">1</td>
                            <td data-label="操作">
                                <button class="btn danger small" @click="deleteBarcode(index)">删除</button>
                            </td>
                            <!-- 根据开关状态决定是否显示列 -->
                            <td v-if="showAndStoreDetails" data-label="款号">{{ getProductInfo(barcode).spdm }}</td>
                            <td v-if="showAndStoreDetails" data-label="颜色">{{ getProductInfo(barcode).ggmc }}</td>
                            <td v-if="showAndStoreDetails" data-label="颜色代码">{{ getProductInfo(barcode).ggdm }}</td>
                            <td v-if="showAndStoreDetails" data-label="尺码">{{ getProductInfo(barcode).ggmc2 }}</td>
                            <td v-if="showAndStoreDetails" data-label="尺码代码">{{ getProductInfo(barcode).ggdm2 }}</td>
                        </tr>
                    </tbody>
                </table>
            </div>

            <!-- 分页控件 -->
            <div class="pagination">
                <button class="btn" @click="prevPage" :disabled="currentPage === 1">上一页</button>
                <span>第 {{ currentPage }} 页 / 共 {{ totalPages }} 页</span>
                <button class="btn" @click="nextPage" :disabled="currentPage === totalPages">下一页</button>
            </div>
            <div class="subtitle"> 支持第三方ERP导入<a class="help-link" href="help.jpg" target="_blank">IPOS导入指南</a> |
                @TIMI 开发</div>
        </div>
    </div>
    <script>
        new Vue({
            el: '#app',
            data() {
                return {
                    barcode: '',
                    barcodes: [],
                    spmc: '',
                    spdm: '',
                    ggmc: '',
                    ggmc2: '',
                    ggdm: '',
                    ggdm2: '',
                    productInfoMap: {}, // 用于存储每个条码对应的商品信息
                    showAndStoreDetails: true, // 商品详情,打开连网查询，关闭则为离线方式
                    allowDuplicateBarcodes: true, //唯一码
                    currentPage: 1, // 当前页码
                    itemsPerPage: 12, // 每页显示的记录数
                    trimLength: 12 // 默认截取位数为 12
                }
            },
            computed: {
                // 计算总页数
                totalPages() {
                    return Math.max(1, Math.ceil(this.barcodes.length / this.itemsPerPage));
                },
                // 计算当前页显示的数据
                paginatedBarcodes() {
                    const start = (this.currentPage - 1) * this.itemsPerPage;
                    const end = start + this.itemsPerPage;
                    return this.barcodes.slice(start, end);
                }
            },
            mounted() {
                this.loadFromLocalStorage();
                this.focusInput(); // 初始聚焦
            },
            methods: {
                focusInput() {
                    this.$refs.barcodeInput.focus(); // 聚焦输入框
                },
                getTotalQuantity() {
                    return this.barcodes.length;
                },
             
                exportToExcel() {
                    if (this.barcodes.length === 0) {
                        alert('没有数据可导出');
                        return;
                    }

                    try {
                        const worksheetData = this.barcodes.map((barcode) => {
                            const info = this.getProductInfo(barcode);
                            const baseData = {
                                唯一码: barcode,
                                商品条码: this.getProductCode(barcode),
                                数量: 1
                            };
                            if (this.showAndStoreDetails) {
                                return {
                                    ...baseData,
                                    款号: info.spdm,
                                    颜色: info.ggmc,
                                    颜色代码: info.ggdm,
                                    尺码: info.ggmc2,
                                    尺码代码: info.ggdm2
                                };
                            }
                            return baseData;
                        });

                        const worksheet = XLSX.utils.json_to_sheet(worksheetData);
                        const workbook = XLSX.utils.book_new();
                        XLSX.utils.book_append_sheet(workbook, worksheet, '条码');
                        XLSX.writeFile(workbook, '条码.xlsx');
                    } catch (err) {
                        console.error('导出 Excel 失败:', err);
                        alert('导出 Excel 失败，请检查数据格式或库是否正确加载');
                    }
                },

                isDuplicateBarcode(barcode) {
                    return this.barcodes.filter(b => b === barcode).length > 1;
                },

           
                addBarcode() {
                    this.barcode = (this.barcode || '').trim();
                    if (!/^\d{16}$/.test(this.barcode)) {
                        alert('无效的条码！请输入一个16位数字条码。');
                        this.barcode = '';
                        this.focusInput();
                        return;
                    }

                    if (this.allowDuplicateBarcodes && this.barcodes.includes(this.barcode)) {
                        alert('条码已扫描，不允许重复添加！如需允许添加，请修改唯一码控制选项。');
                        this.barcode = '';
                        this.focusInput();
                        return;
                    }

                    if (this.showAndStoreDetails) {
                        this.getColorSize(this.barcode)
                            .then(() => {
                                this.barcodes.unshift(this.barcode);
                                this.barcode = '';
                                this.saveToLocalStorage();
                                this.focusInput();
                            })
                            .catch(() => {
                                alert('条码添加不成功，请检查条码是否正确以及截取位数是否合理');
                                this.barcode = '';
                                this.focusInput();
                            });
                    } else {
                        this.barcodes.unshift(this.barcode);
                        this.barcode = '';
                        this.saveToLocalStorage();
                        this.focusInput();
                    }
                },
                getProductCode(barcode) {
                    return barcode.substring(0, this.trimLength); // 使用 trimLength 动态截取

                },
                getQuantity(barcode) {
                    return this.barcodes.filter(b => b === barcode).length;
                },
                deleteBarcode(index) {
                    this.barcodes.splice(index, 1);
                    this.saveToLocalStorage();
                    this.focusInput(); // 重新聚焦
                },
           
                saveToLocalStorage() {
                    try {
                        localStorage.setItem('barcodes', JSON.stringify(this.barcodes));
                        if (this.showAndStoreDetails) {
                            localStorage.setItem('productInfoMap', JSON.stringify(this.productInfoMap));
                        } else {
                            localStorage.removeItem('productInfoMap');
                        }
                    } catch (err) {
                        console.error('保存到 localStorage 失败:', err);
                        alert('保存数据失败，请检查浏览器存储空间');
                    }
                },

                loadFromLocalStorage() {
                    try {
                        const storedData = localStorage.getItem('barcodes');
                        if (storedData) {
                            this.barcodes = JSON.parse(storedData);
                        }
                        if (this.showAndStoreDetails) {
                            const storedInfoMap = localStorage.getItem('productInfoMap');
                            if (storedInfoMap) {
                                this.productInfoMap = JSON.parse(storedInfoMap);
                            }
                        }
                    } catch (err) {
                        console.error('从 localStorage 加载数据失败:', err);
                        alert('加载数据失败，请检查浏览器存储');
                    }
                },
                clearLocalStorage() {
                    const isConfirmed = confirm('确定要清空所有条码数据吗？此操作不可恢复！');
                    if (isConfirmed) {
                        localStorage.removeItem('barcodes');
                        localStorage.removeItem('productInfoMap');
                        this.barcodes = [];
                        this.productInfoMap = {};
                        //alert('数据已清空！');
                        this.focusInput(); // 重新聚焦
                    }
                },
             
                getColorSize(barcode) {
                    return new Promise((resolve, reject) => {
                        fetch(`http://127.0.0.1/api`, {
                            method: 'POST',
                            headers: {
                                'Content-Type': 'application/json',
                            },
                            body: JSON.stringify({
                                sptm: barcode.substring(0, this.trimLength),
                            }),
                        })
                            .then(res => {
                                if (!res.ok) {
                                    throw new Error('网络请求失败');
                                }
                                return res.json();
                            })
                            .then(data => {
                                if (!Array.isArray(data) || data.length === 0) {
                                    throw new Error('返回数据格式不正确');
                                }
                                this.spmc = data[0].spmc || '';
                                this.spdm = data[0].spdm || '';
                                this.ggmc = data[0].ggmc || '';
                                this.ggmc2 = data[0].ggmc2 || '';
                                this.ggdm = data[0].ggdm || '';
                                this.ggdm2 = data[0].ggdm2 || '';
                                this.productInfoMap[barcode] = {
                                    spdm: this.spdm,
                                    ggmc: this.ggmc,
                                    ggmc2: this.ggmc2,
                                    ggdm: this.ggdm,
                                    ggdm2: this.ggdm2
                                };
                                resolve();
                            })
                            .catch(err => {
                                console.error(err);
                                alert('获取商品信息失败，请检查网络或条码是否正确');
                                reject();
                            });
                    });
                },
                getProductInfo(barcode) {
                    return this.productInfoMap[barcode] || { spdm: '', ggmc: '', ggmc2: '', ggdm: '', ggdm2: '' };
                },
                // 上一页
                prevPage() {
                    if (this.currentPage > 1) {
                        this.currentPage--;
                    }
                },
                // 下一页
                nextPage() {
                    if (this.currentPage < this.totalPages) {
                        this.currentPage++;
                    }
                }
            }
        });
    </script>

    <style>
        .subtitle {
            text-align: center;
            /* 文本水平居中 */
            font-size: 0.8rem;
            color: #7f8c8d;
            margin-top: 10px;
            /* 添加上边距 */
            margin-bottom: 10px;
            /* 添加下边距 */
        }

        .help-link {
            color: #3498db;
            /* 链接颜色 */
            text-decoration: none;
            /* 去掉下划线 */
            transition: color 0.3s ease;
            /* 添加颜色过渡效果 */
        }

        .help-link:hover {
            color: #e74c3c;
            /* 鼠标悬停时改变颜色 */
        }

        /* 分页样式 */
        .pagination {
            display: flex;
            justify-content: center;
            align-items: center;
            gap: 10px;
            margin-top: 20px;
            margin-bottom: 20px;
        }

        .pagination .btn {
            padding: 8px 16px;
            border: none;
            border-radius: 6px;
            font-size: 14px;
            cursor: pointer;
            transition: all 0.3s ease;
            background-color: #3498db;
            color: white;
        }

        .pagination .btn:disabled {
            background-color: #bdc3c7;
            cursor: not-allowed;
        }

        .pagination span {
            font-size: 14px;
            color: #2c3e50;
        }

        /* 红色标记重复记录 */
        .duplicate-barcode {
            color: red;
        }

        /* 总数样式 */
        .total-number {
            display: inline-block;
            padding: 5px 10px;
            background-color: red;
            color: white;
            border-radius: 50%;
            font-size: 20px;
            transition: transform 0.3s ease;
        }

        .animate {
            animation: bounce 0.5s;
        }

        /* 基础样式 */
        * {
            box-sizing: border-box;
            margin: 0;
            padding: 0;
        }

        body {
            font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
            line-height: 1.4;
            background-color: #f5f5f5;
        }

        .container {
            max-width: 900px;
            margin: 0 auto;
            padding: 10px;
            background-color: white;
            box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
            border-radius: 8px;
        }

        /* 头部样式 */
        .header {
            text-align: center;
            margin-bottom: 10px;
        }

        .title {
            font-size: 1.5rem;
            color: #2c3e50;
            margin-bottom: 3px;
        }

        .subtitle {
            color: #7f8c8d;
            font-size: 0.8rem;

        }

        /* 控制面板 */
        .control-panel {
            margin-bottom: 10px;
        }

        .input-total-container {
            display: flex;
            align-items: center;
            justify-content: space-between;
        }

        .input-box {
            width: 50%;
            padding: 8px;
            font-size: 14px;
            border: 1px solid #3498db;
            border-radius: 6px;
            margin-bottom: 0;
        }

        .total-panel {

            font-size: 1rem;
            padding: 10px;
            background: white;


        }

        .button-group {
            display: grid;
            grid-template-columns: repeat(3, 1fr);
            gap: 8px;
            margin-bottom: 8px;
        }

        /* 按钮样式 */
        .btn {
            padding: 8px;
            border: none;
            border-radius: 6px;
            font-size: 12px;
            cursor: pointer;
            transition: all 0.3s ease;
        }

        .btn.primary {
            background-color: #3498db;
            color: white;
        }

        .btn.success {
            background-color: #27ae60;
            color: white;
        }

        .btn.danger {
            background-color: #e74c3c;
            color: white;
        }

        .btn.small {
            padding: 4px 8px;
            font-size: 11px;
        }

        /* 当前商品信息 - 紧凑样式 */
        .current-info.compact {
            background: white;
            border-radius: 8px;
            padding: 8px;
            margin-bottom: 10px;
            box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
            overflow: hidden;
        }

        .current-info.compact .info-row {
            display: flex;
            flex-wrap: nowrap;
            gap: 10px;
            overflow-x: auto;
        }

        .current-info.compact .info-item {
            flex: 1;
            min-width: auto;
            padding: 6px;
            background: #f8f9fa;
            border-radius: 4px;
            font-size: 0.8rem;
            white-space: nowrap;
        }

        .current-info.compact .info-item label {
            color: #7f8c8d;
            margin-right: 5px;
        }

        /* 表格样式 */
        .table-container {
            overflow-x: auto;
            margin-bottom: 10px;
            background: white;
            border-radius: 8px;
            box-shadow: 0 1px 3px rgba(0, 0, 0, 0.1);
        }

        .bordered-table {
            width: auto;
            border-collapse: collapse;
            min-width: 100%;
        }

        .bordered-table th,
        .bordered-table td {
            padding: 8px;
            text-align: left;
            border-bottom: 1px solid #ecf0f1;
            font-size: 12px;
            white-space: nowrap;
        }

        .bordered-table th {
            background-color: #3498db;
            color: white;
            font-weight: 500;
        }

        .bordered-table tr:nth-child(even) {
            background-color: #f8f9fa;
        }

        /* 移动端适配 */
        @media (max-width: 480px) {
            .title {
                font-size: 1.2rem;
            }

            .input-total-container {
                flex-direction: column;
            }

            .input-box {
                width: 100%;
                margin-bottom: 8px;
            }

            .total-panel {
                width: 100%;
            }

            .current-info.compact.info-item {
                min-width: 100%;
                font-size: 0.7rem;
            }

            .btn {
                padding: 6px;
                font-size: 11px;
            }

            .bordered-table th,
            .bordered-table td {
                padding: 6px;
                font-size: 11px;
            }

            /* 隐藏表格单元格前的标题 */
            .bordered-table td:before {
                display: none;
            }
        }
    </style>
</body>

</html>